/*
 * $Id: sysapi_path.c,v 1.18 2005-12-27 16:22:39 bacon Exp $
 */

#include <xp/bas/sysapi.h>
#include <xp/bas/locale.h>
#include <xp/bas/wstring.h>
#include <xp/bas/errno.h>
#include <stdio.h> /* for rename */

#if defined(_WIN32) && !defined(INVALID_FILE_ATTRIBUTES)
#define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
#endif

int xp_stat (const xp_char_t* path, xp_stat_t* buf)
{
#ifdef XP_CHAR_IS_MCHAR
	return stat (path, buf);
#else
	xp_mchar_t path_mb[XP_PATH_MAX + 1];
	if (xp_wcstomcs_strict(path, path_mb, xp_countof(path_mb)) == -1) {
		return -1;
	}
	return stat (path_mb, buf);
#endif
}

int xp_unlink (const xp_char_t* path)
{
#ifdef _WIN32
	if (DeleteFile(path) == 0) {
		xp_seterrno (xp_maperrno(GetLastError()));
		return -1;
	}
	return 0;
#else

#ifdef XP_CHAR_IS_MCHAR
	return unlink (path);
#else
	xp_mchar_t path_mb[XP_PATH_MAX + 1];
	if (xp_wcstomcs_strict(path, path_mb, xp_countof(path_mb)) == -1) {
		return -1;
	}
	return unlink (path_mb);
#endif

#endif
}

int xp_rename (const xp_char_t* opath, const xp_char_t* npath)
{
#ifdef _WIN32
	if (MoveFile(opath, npath) == 0) {
		xp_seterrno (xp_maperrno(GetLastError()));
		return -1;
	}
	return 0;
#else

#ifdef XP_CHAR_IS_MCHAR
	return rename (opath, npath);
#else
	xp_mchar_t opath_mb[XP_PATH_MAX + 1];
	xp_mchar_t npath_mb[XP_PATH_MAX + 1];
	if (xp_wcstomcs_strict(opath, opath_mb, xp_countof(opath_mb)) == -1) {
		return -1;
	}
	if (xp_wcstomcs_strict(npath, npath_mb, xp_countof(npath_mb)) == -1) {
		return -1;
	}
	return rename (opath_mb, npath_mb);
#endif

#endif
}

int xp_access (const xp_char_t* path, int option)
{
#ifdef _WIN32
	DWORD attr = GetFileAttributes (path);
	if (attr == INVALID_FILE_ATTRIBUTES) {
		xp_seterrno (xp_maperrno(GetLastError()));
		return -1;
	}

	if ((attr & FILE_ATTRIBUTE_READONLY) && (option & XP_ACCESS_WRITE)) {
		xp_seterrno (XP_EACCES);
		return -1;
	}

	return 0;

#else

#ifdef XP_CHAR_IS_MCHAR
	return access (path, option);
#else
	xp_mchar_t path_mb[XP_PATH_MAX + 1];
	if (xp_wcstomcs_strict(path, path_mb, xp_countof(path_mb)) == -1) {
		return -1;
	}
	return access (path_mb, option);
#endif

#endif
}

int xp_chmod (const xp_char_t* path, xp_mode_t mode)
{
#ifdef _WIN32
	DWORD attr = GetFileAttributes (path);
	if (attr == INVALID_FILE_ATTRIBUTES) {
		xp_seterrno (xp_maperrno(GetLastError()));
		return -1;
	}

	if (mode & S_IWRITE) { /* TODO: replay S_IWRITE by xpkit's own definition */
		attr &= ~FILE_ATTRIBUTE_READONLY;
	}
	else {
		attr |= FILE_ATTRIBUTE_READONLY;
	}

	if (SetFileAttributes(path, attr) == 0) {
		xp_seterrno (xp_maperrno(GetLastError()));
		return -1;
	}

	return 0;
#else

#ifdef XP_CHAR_IS_MCHAR
	return chmod (path, mode);
#else
	xp_mchar_t path_mb[XP_PATH_MAX + 1];
	if (xp_wcstomcs_strict(path, path_mb, xp_countof(path_mb)) == -1) {
		return -1;
	}
	return chmod (path_mb, mode);
#endif

#endif
}
